<script setup lang="ts">
import {onBeforeMount, provide, ref} from "vue"
import {SelectOption} from "naive-ui"
import {
  StnTable,
  StnDataTableColumns,
  StnTableOperations,
  StnTableColSetting, useTipStore, TipMessageTypeConst,
} from 'st-ui-vue3-navie'
import {ResType, ResObjPropNameConst} from "st-common-req"
import {funThrottleByLimit} from 'st-common-core'
import {useLoadingStore} from "@loading"
import NaPaginationResponsive from '../NaPaginationResponsive/NaPaginationResponsive.vue'
import AddBtn from "../AddBtn/AddBtn.vue"
import DelBtn from "../DelBtn/DelBtn.vue"

/**
 * 组件参数
 */
const {
  title = '',
  columns = [],
  data = [],
  rowKey = (rowData: Record<string, any>) => rowData.id,
  cascade = false,
  loading = false,
  getDataHandler = () => Promise.resolve({
    [ResObjPropNameConst.STATUS]: true,
    [ResObjPropNameConst.MESSAGE]: '获取数据成功'
  }),
  isGetDataOnBeforeMount = true,
  pageSizeDefault = 10,
  pageSizes = [1, 5, 10, 20, 30],
  addHandler = () => {
  },
  isBatchDelCascadeConfirm = false,
  batchDelCascadeConfirmText = '是否级联删除？',
  delHandler = () => Promise.resolve({
    [ResObjPropNameConst.STATUS]: true,
    [ResObjPropNameConst.MESSAGE]: '删除数据成功'
  }),
  isCascadeBtn = false,
  isExpandAllBtn = false,
  showEditorHandler = () => {
  },
} = defineProps<{
  // 标题
  title?: string;
  // 表格列配置
  columns?: StnDataTableColumns;
  // 表格数据
  data?: Record<string, any>[];
  // 表格行的主键
  rowKey?: (rowData: Record<string, any>) => number | string;
  // 表格数据勾选是否级联
  cascade?: boolean;
  // 表格是否为加载状态
  loading?: boolean;
  // 获取表格数据的处理函数
  getDataHandler?: () => Promise<ResType>;
  // 组件挂载前是否需要获取表格数据
  isGetDataOnBeforeMount?: boolean;
  // 分页每页数据个数的默认值
  pageSizeDefault?: number;
  // 分页每页数据个数选择器的选项
  pageSizes?: number[];
  // 新增按钮点击事件处理函数
  addHandler?: () => void;
  // 是否开启批量删除按钮级联删除确认
  isBatchDelCascadeConfirm?: boolean;
  // 批量删除按钮级联删除确认文本
  batchDelCascadeConfirmText?: string;
  // 删除表格数据处理函数
  delHandler?: (rowKeys: (number | string)[], cascade: boolean) => Promise<ResType>;
  // 是否开启表格数据级联勾选控制按钮
  isCascadeBtn?: boolean;
  // 是否开启展开表格数据所有可展开行的控制按钮
  isExpandAllBtn?: boolean;
  // 展示表格数据编辑对话框的处理函数
  showEditorHandler?: (row: Record<string, any>) => void;
}>()

/**
 * 双向数据绑定
 */
// 当前选中的数据行主键组成的列表
const rowKeys = defineModel<(number | string)[]>('rowKeys', {default: []})

// 向子组件提供展示表格数据编辑对话框的处理函数
provide<(form: Record<string, any>) => void>('showTableDataEditor', showEditorHandler)

/**
 * 获取表格数据
 */
const getTableDataHandler = async () => {
  // 获取表格数据
  const res = await getDataHandler()
  // 如果请求获取数据被节流，得到的返回结果为 undefined
  if (res === undefined) return
  // 获取表格数据成功
  if (res[ResObjPropNameConst.STATUS]) useTipStore().message(res[ResObjPropNameConst.MESSAGE], TipMessageTypeConst.SUCCESS)
  else useTipStore().message(res[ResObjPropNameConst.MESSAGE], TipMessageTypeConst.ERROR)
}
onBeforeMount(async () => {
  // 如果组件挂载前无需获取表格数据，则直接返回
  if (!isGetDataOnBeforeMount) return
  // 获取表格数据
  await getTableDataHandler()
})

/**
 * 根据表格的列配置计算表格的 scroll x
 */
const scrollX = ref(0)
const getScrollX = (columns: StnDataTableColumns) => {
  scrollX.value = columns.reduce((acc, curColumn) => {
    return acc + (curColumn.checked ? (curColumn.width as number ?? 120) : 0)
  }, 0) + 20
}

/**
 * 分页
 */
// 分页每页数据个数
const pageSize = ref<number>(pageSizeDefault)

/**
 * 删除表格数据
 */
// 当前是否处于表格数据删除中状态
const isTableDataDeleting = ref(false)
const delTableDataHandler = funThrottleByLimit({
  fun: async (rowKeys: (number | string)[], cascade?: boolean) => {
    // 标记表格数据删除中状态
    isTableDataDeleting.value = true
    setTimeout(() => {
      // 删除表格数据完成
      if (!isTableDataDeleting.value) return
      // 如果仍在删除状态，开启加载动画
      useLoadingStore().loading()
    }, 500)
    // 调用删除表格数据处理函数
    return await delHandler(rowKeys, cascade)
      .catch((res: ResType) => {
        useTipStore().message(res[ResObjPropNameConst.MESSAGE], TipMessageTypeConst.ERROR)
      })
      .finally(() => {
        // 标记删除表格数据完成
        isTableDataDeleting.value = false
        // 关闭加载动画
        useLoadingStore().loaded()
      })
  }
})
provide<(rowKeys: (number | string)[], cascade?: boolean) => Promise<ResType>>('delTableDataHandler', delTableDataHandler)
</script>

<template>
  <div class="manager-table w-full h-full">
    <NaPaginationResponsive>
      <template #default="{isSimple}">
        <StnTable
          :title="title"
          :columns="columns"
          :data="data"
          :rowKey="rowKey"
          v-model:checked-row-keys="rowKeys"
          :scrollX="scrollX"
          :loading="loading"
          :cascade="cascade"
          :pagination="{
            pageSize: pageSize,
            'onUpdate:pageSize': (size: number) => pageSize = size,
            showSizePicker: true,
            pageSizes: pageSizes,
            selectProps: {
              renderLabel: (option: SelectOption) => `${option.value} / 页`,
            },
            showQuickJumper: true,
            goto: () => '跳至',
            simple: isSimple,
          }"
          @col-showed-change="getScrollX"
        >
          <template #search>
            <slot name="search"/>
          </template>
          <template #operations>
            <StnTableOperations
              :cascade="isCascadeBtn"
              :expand-all="isExpandAllBtn"
              @refresh="getTableDataHandler"
            >
              <template #add="{isCollapse}">
                <AddBtn
                  :is-collapse="isCollapse"
                  @click="addHandler"
                />
              </template>
              <template #batch-del="{isCollapse}">
                <DelBtn
                  :is-disabled="rowKeys.length === 0"
                  :is-collapse="isCollapse"
                  text="批量删除"
                  :is-cascade-confirm="isBatchDelCascadeConfirm"
                  :cascade-confirm-text="batchDelCascadeConfirmText"
                  @positive-click="(isCollapse: boolean) => delTableDataHandler(rowKeys, isCollapse)"
                />
              </template>
              <template #affix="{isCollapse}">
                <StnTableColSetting :btn-collapse="isCollapse"/>
              </template>
            </StnTableOperations>
          </template>
        </StnTable>
      </template>
    </NaPaginationResponsive>
  </div>
</template>

<style scoped>

</style>
